package com.example.myproject.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;


/**
 * 解析 json 得到具体字段的 jsonPath。
 *
 * @author Jan
 * @date 2023/08
 */
public class JsonPathParser {

    static {
        // 设置全局白名单，解析 pb3 中的 @type 类型。
        ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
    }

    private JsonPathParser() {
    }

    /**
     * 得到json路径。
     *
     * @param jsonStr json str
     * @return {@link Set}<{@link String}>
     */
    public static Set<String> getJsonPaths(String jsonStr) {
        // 解析JSON字符串为JSON对象。
        JSONObject jsonObj = JSON.parseObject(jsonStr);

        // 存储JSONPath路径的集合。
        Set<String> jsonPaths = new HashSet<>();

        // 递归遍历JSON对象的所有字段，并提取出JSONPath路径。
        parseJsonObj(jsonObj, "$", jsonPaths);

        return jsonPaths;

    }

    /**
     * 解析 json 对象。
     *
     * @param jsonObj    json obj。
     * @param parentPath 父路径。
     * @param jsonPaths  json路径。
     */
    private static void parseJsonObj(JSONObject jsonObj, String parentPath, Set<String> jsonPaths) {

        for (Map.Entry<String, Object> entry : jsonObj.entrySet()) {
            String key = entry.getKey();
            // 跳过PBv3的类型标识。
            if (key.contains("@type")) {
                continue;
            }
            Object value = jsonObj.get(key);
            String currPath = parentPath + "." + key;

            // 将当前字段的JSONPath路径添加到集合中。
            jsonPaths.add(currPath);

            if (value instanceof JSONObject) {
                // 递归处理嵌套的JSON对象。
                parseJsonObj((JSONObject) value, currPath, jsonPaths);
            } else if (value instanceof JSONArray) {
                // 递归处理嵌套的JSON数组。
                parseJsonArray((JSONArray) value, currPath, jsonPaths);
            }
        }
    }

    /**
     * 解析 json 数组。
     *
     * @param jsonArray  json数组。
     * @param parentPath 父路径。
     * @param jsonPaths  json路径。
     */
    private static void parseJsonArray(JSONArray jsonArray, String parentPath, Set<String> jsonPaths) {
        for (int i = 0; i < jsonArray.size(); i++) {
            // 只取集合中第一个元素的字段。
            if (0 < i) {
                continue;
            }

            Object value = jsonArray.get(i);
            String currPath = parentPath + "[" + i + "]";

            if (value instanceof JSONObject) {
                // 递归处理嵌套的JSON对象。
                parseJsonObj((JSONObject) value, currPath, jsonPaths);
            } else if (value instanceof JSONArray) {
                // 递归处理嵌套的JSON数组。
                parseJsonArray((JSONArray) value, currPath, jsonPaths);
            }
        }
    }
}

